﻿#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

/**  串口可以看到这个分区表
 * Creating 8 MTD partitions on "spi0.0":
 * 0x000000037000 - 0x0000001b7000 : "KERNEL"
 * 0x0000001b7000 - 0x0000001b8000 : "MAC"
 * 0x0000001b8000 - 0x0000001b9000 : "ENV"
 * 0x0000001b9000 - 0x0000002b9000 : "A"		// squashfs /dev/mtdblock4	/root根目录
 * 0x0000002b9000 - 0x000000452000 : "B"		// squashfs /dev/mtdblock5 /usr
 * 0x000000452000 - 0x000000604000 : "C"		// squashfs /dev/mtdblock6 /mvs
 * 0x000000604000 - 0x000000677000 : "D"		// squashfs /dev/mtdblock7 /ext
 * 0x000000677000 - 0x0000007f7000 : "E"		// jffs2 /dev/mtdblock8 /mnt/mtd 
 */

typedef struct 
{
	char name[100];
	long start_offset;
	long end_offset;
} zone_info;

#define SRC_BIN_FILE	"flash.bin"		// 输入源文件
#define DTS_BIN_FILE	"flash_new.bin"	// 输入文件

#define ZONE_NUM		8				// 分区个数

// 分区表
zone_info table[ZONE_NUM] =
{
	{"1.KERNEL.bin", 0x000000037000, 0x0000001b7000},
	{"2.MAC.bin", 0x0000001b7000, 0x0000001b8000},
	{"3.ENV.bin", 0x0000001b8000, 0x0000001b9000},
	{"4.root.bin", 0x0000001b9000, 0x0000002b9000},
	{"5.usr.bin", 0x0000002b9000, 0x000000452000},
	{"6.mvs.bin", 0x000000452000, 0x000000604000},
	{"7.ext.bin", 0x000000604000, 0x000000677000},
	{"8.mtd.bin", 0x000000677000, 0x0000007f7000}
};

// 文件分割
bool excision()
{
	long file_len = 0;
	FILE *in;
	// 读取大小
	in = fopen(SRC_BIN_FILE, "rb");
	if (in == NULL)
	{
		printf("open %s error\n", SRC_BIN_FILE);
		return false;
	}
	fseek(in, 0, SEEK_END);
	file_len = ftell(in);
	printf("[%s] input file size: %d byte\n", __func__, file_len);
	// 循环读取
	for(int i=0; i< ZONE_NUM; i++)
	{
		long len = table[i].end_offset - table[i].start_offset;
		char* buffer = new char[len];
		FILE* out = fopen(table[i].name, "wb");
		if (out != NULL)
		{
			fseek(in, table[i].start_offset, SEEK_SET);
			fread(buffer, 1, len, in);
			fwrite(buffer, 1, len, out);
			fclose(out);
		}
		delete[] buffer;
		printf("\toutput: %s\n", table[i].name);
	}
	fclose(in);
	return true;
}

// 文件合并
bool merge()
{
	long file_len = 0;
	FILE* in;
	// 读取大小
	in = fopen(SRC_BIN_FILE, "rb");
	if (in == NULL)
	{
		printf("open %s error\n", SRC_BIN_FILE);
		return false;
	}
	fseek(in, 0, SEEK_END);
	file_len = ftell(in);
	printf("[%s] input file size: %d byte\n", __func__, file_len);
	// 读取源文件到内存 - 因为只要替换我们可以修改的空间
	char* buffer = new char[file_len];
	fseek(in, 0, SEEK_SET);
	fread(buffer, 1, file_len, in);
	fclose(in);
	// 循环读取
	for (int i = 0; i < ZONE_NUM; i++)
	{
		long len = table[i].end_offset - table[i].start_offset;
		memset(buffer + table[i].start_offset, 0xFF, len); // 全值为0xFF
		// 读取
		FILE* item_file = fopen(table[i].name, "rb");
		if(item_file == NULL) continue;
		printf("\tread: %s\n", table[i].name);
		fseek(item_file, 0, SEEK_END);
		long item_file_len = ftell(item_file);
		fseek(item_file, 0, SEEK_SET);
		fread(buffer + table[i].start_offset, 1, item_file_len, item_file);
		fclose(item_file);
	}
	// 输出
	FILE* out = fopen(DTS_BIN_FILE, "wb");
	if (out == NULL) return false;
	fwrite(buffer, 1, file_len, out);
	delete[] buffer;
	fclose(out);
	printf("output: %s\n", DTS_BIN_FILE);
	return true;
}

int main()
{
	if (excision())
	{
		puts("excision complete, please pause any key continue merge!");
		_getch();
		merge();
		puts("merge complete!");
	}
	puts("\nplease pause any key continue exit!");
	_getch();
	return 0;
}

